/*****************************************************************//**
 * \file   AnsysAPDLReader_NBLOCK.cpp
 * \brief  AnsysAPDLReader_NBLOCK
 *
 * \author Wyatt
 * \date   May 2023
 *********************************************************************/
#include "AnsysAPDLReader_NBLOCK.h"
#include "CDBReader.h"
#include "Includes.h"
#include "TxtMemStream.h"
#include <algorithm>

#include "AnsysAPDLReader_Select.h"

IMPLEMENT_CDB_READER(AnsysAPDLReader_NBLOCK, KEY_NBLOCK, "NBLOCK")

AnsysAPDLReader_NBLOCK::AnsysAPDLReader_NBLOCK(CDBReader* pCDBReader)
	: ReaderBase(pCDBReader)
{
}

bool AnsysAPDLReader_NBLOCK::Scan(std::string& strDataLine)
{
	if (_inBlock == IN_NONE) {
		return ScanHead(strDataLine);
	}
	return ScanData(strDataLine);
}

bool AnsysAPDLReader_NBLOCK::ScanHead(std::string& strDataLine)
{
	_nLine = 1;
	std::vector<std::string> vecData;
	int n = splitView(strDataLine, vecData, ",", true, false);
	if (n < 2)
		return false;
	for (int i = 0; i < n; i++)
	{
		std::string str(vecData[i]);
		switch (i)
		{
		case 1:
			if (!string2Integer(str, _nCellNum))
				return false;
			break;
		case 2:
			toUpper(str);
			if (str == "SOLID")
				_bSolid = true;
			break;
		case 3:
			if (!string2Integer(str, NDMAX))
				return false;
			break;
		case 4:
			if (!string2Integer(str, NDSEL))
				return false;
			break;
		}
	}
	_nodeCnt = 0;
	_inBlock = IN_YES;
	return true;
}

bool AnsysAPDLReader_NBLOCK::ScanData(std::string& strDataLine)
{
	if (strDataLine.compare("-1") >= 0)
	{
		_nLine++;
		_inBlock = IN_NONE;
		return true;
	}
	_nodeCnt++;
	_nLine++;
	return true;
}

bool AnsysAPDLReader_NBLOCK::Read(std::string& strDataLine)
{
	if (_inBlock == IN_NONE) {
		return ReadHead(strDataLine);
	}
	return ReadData(strDataLine);
}

bool AnsysAPDLReader_NBLOCK::ReadHead(std::string& strDataLine)
{
	_nodeIdRead.clear();
	_nodeIdRead.reserve(_nodeCnt);
	_nLine = 1;
	if (_nodeCnt > 8){
		unsigned long test = _nodeCnt;
		_pCDBReader->GetNodeVecHlp().reserve(test);
	}
	if (_pCDBReader->fs()->getline(_strFormat))
	{
		removeChar(_strFormat, ')');
		removeChar(_strFormat, '(');
		std::vector<std::string> vecData;
		int n = split(_strFormat, vecData);
		if (n < 2) return false;
		for (int idata = 0; idata < vecData.size(); idata++)
		{
			std::string sdata(vecData[idata]);
			if (idata == 0)
			{
				std::vector<std::string> sdata_x;
				int ndx = split(sdata, sdata_x, "iI");
				for (int idata_x = 0; idata_x < sdata_x.size(); idata_x++)
				{
					std::string sdata_xi(sdata_x[idata_x]);
					if (idata_x == 0)
					{
						if (!string2Integer(sdata_xi, nI))
							return false;
					}
					else if (idata_x == 1)
					{
						if (!string2Integer(sdata_xi, wI))
							return false;
					}
				}
			}
			else if (idata == 1)
			{
				std::vector<std::string> sdata_x;
				int ndx = split(sdata, sdata_x, "eEgG");
				for (int idata_x = 0; idata_x < sdata_x.size(); idata_x++)
				{
					std::string sdata_xi(sdata_x[idata_x]);
					if (idata_x == 0)
					{
						if (!string2Integer(sdata_xi, nd))
							return false;
					}
					else if (idata_x == 1)
					{
						size_t nDotPos = sdata_xi.find_first_of(".");
						if (nDotPos != std::string::npos)
						{
							if (!string2Integer(stringLeft(sdata_xi, nDotPos), wd))
								return false;
						}
						else
						{
							string2Integer(sdata_xi, wd);
						}
					}
					else if (idata_x == 2)
					{
						string2Integer(sdata_xi, wexp);
					}
				}
			}
		}
	}
	if (nI != 0 && wI != 0 && nd != 0 && wd!= 0)
	{
		for (int i = 0;i< nI;i++)
		{
			node_coord_control.emplace_back(wI);
		}
		for (int i = 0; i < nd; i++)
		{
			node_coord_control.emplace_back(wd);
		}
	}
	_inBlock = IN_YES;
	return true;
}

bool AnsysAPDLReader_NBLOCK::ReadData(std::string& strDataLine)
{
	std::string strDataView(strDataLine);
	if (strDataView.substr(0, 2).compare("-1") >= 0)
	{
		AnsysAPDLReader_NSEL::_instance->_nodeSelected.clear();
		AnsysAPDLReader_NSEL::_instance->_nodeSelected.selType = ANSYS_TARGET_TYPE::TARGET_NODE;
		AnsysAPDLReader_NSEL::_instance->_nodeSelected.selectData = _nodeIdRead;
		_nLine++;
		_inBlock = IN_NONE;
		return true;
	}
	SKey nid = 0;
	SNum3d vPos;

	std::vector<std::string> resultSplit;
	//split(strDataView, resultSplit, " ", true, true);
	split_node_coord(strDataView, resultSplit,node_coord_control);

	int control_int; double control_doub;
	if (string2Integer(resultSplit[1], control_int))
	{
		for (int ipox = 0; ipox < 6; ipox++)
		{
			std::string str;
			switch (ipox)
			{
			case 0:
			{
				if (!string2Integer(resultSplit[0], nid))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_ID);
					throw;
				}
			}
			break;
			case 1:
			case 2:
				break;
			case 3:
				if (resultSplit[3].empty())
					break;
				if (!string2Double(resultSplit[3], vPos[0]))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_VALUE);
					throw ;
				}
				break;
			case 4:
				if (resultSplit[4].empty())
					break;
				if (!string2Double(resultSplit[4], vPos[1]))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_VALUE);
					throw ;
				}
				break;
			case 5:
				if (resultSplit[5].empty())
					break;
				if (!string2Double(resultSplit[5], vPos[2]))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_VALUE);
					throw ;
				}
				break;
			}
		}
	}
	else
	{
		std::string str;
		for (int i = 0; i < 4; i++)
		{			
			switch (i)
			{
			case 0:				
				//str = TrimView(stringSub(strDataView, i * wI, wI));
				if (resultSplit[i].empty())
					break;
				if (!string2Integer(resultSplit[i], nid))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_ID);
					throw ;
				}
				break;
			case 1:
				//str = TrimView(stringSub(strDataView, i * wI, wd));
				if (resultSplit[i].empty())
					break;
				if (!string2Double(resultSplit[i], vPos[0]))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_VALUE);
					throw ;
				}
				break;
			case 2:
				//str = TrimView(stringSub(strDataView, wI + wd, wd));
				if (resultSplit[i].empty())
					break;
				if (!string2Double(resultSplit[i], vPos[1]))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_VALUE);
					throw ;
				}
				break;
			case 3:
				//str = TrimView(strDataView.substr(wI + 2 * wd, wd));
				if (resultSplit[i].empty())
					break;
				if (!string2Double(resultSplit[i], vPos[2]))
				{
					//ReporterFatal<std::string> rep(str, _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_INVALID_VALUE);
					throw ;
				}
				break;
			}
		}
	}
	if (nid == 0)
	{
		//ReporterFatal<std::string> rep("", _pCDBReader->GetLineNumber(), _pCDBReader->filePath(), REP_FATAL_CODE_NO_NID);
		throw ;
	}
	_nodeIdRead.emplace_back(nid);
	AnsysNode* pNode = new AnsysNode;
	pNode->id = nid;
	pNode->oldId = nid;
	pNode->nLine = _pCDBReader->GetLineNumber();
	pNode->vPos = vPos;
	_pCDBReader->AddNode(nid, pNode);
	_nLine++;
	_pCDBReader->ifBuildMap = false;
	return true;
}
